<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    
  </style>
</head>
<body>
  <span> </span>
  <span> </span>
  <span> </span>
  <span> </span>
  <span> </span>
  <span> </span>
</body>
<script>

  // 深拷贝对象
  // const obj1 = {
  //   name:"admin",
  //   age:19
  // }
  // const obj2 = {}
  // for(let i in obj1){
  //   obj2[i]= obj1[i]
  // }
  // console.log(obj1)
  // console.log(obj2)
  // console.log(obj1 === obj2)

  // 深拷贝数组
  // const arr1 = [1,2,3]
  // const arr2 = []
  // for(let i in arr1){
  //   arr2[i] = arr1[i]
  // }
  // console.log(arr1)
  // console.log(arr2)
  // console.log(arr1 === arr2)

  // 深拷贝函数
  // const fn1 = function(){ console.log("haha") }
  // const fn2 = fn1.bind();
  // console.log(fn1)
  // console.log(fn2)
  // console.log(fn1 === fn2)



  function deepCopy(data){
    // 创建初始值，初始值的类型根据参数类型决定
    const result = Array.isArray(data) ? [] : ( typeof data === "function" ? data.bind() : {} );
    // 数组或对象需要被解析
    for(let i in data){
      // for-in不仅可以遍历对象自身的属性，还会遍历到原型身上的属性
      // 借助：对象.hasOwnProperty( key )判断该属性是否属于对象自身
      if(data.hasOwnProperty(i)){
        // 解析后，检测内部数据类型
        if(typeof data[i] === "object"){
          // 如果内部的数据，还是对象（数组），递归处理
          result[i] = deepCopy(data[i]);
        }else if(typeof data[i] === "function"){
          // 如果内部的数据，是函数，深拷贝函数
          result[i] = data[i].bind(result);
        }else{
          // 如果内部的数据，不是对象（数组），不是函数，直接赋值
          result[i] = data[i];
        }
      }
    }
    // 返回本次拷贝之后的对象
    return result;
  }

  // const data = {name:"admin"};
  // const data = ["hello"];
  // const data = function(){ 1 };
  const data = {
    name:"张三",
    child:[{
      name:"小张",
      child:[{
        name:"小小张",
        msg:{
          a:1,b:2
        },
        show:function(){
          console.log(this.name);
        }
      }],
      show:function(){
        console.log(this.name);
      }
    }],
    msg:{a:"a",b:"b"},
    show:function(){
      console.log(this.name);
    }
  };
  const data2 = deepCopy(data);

  console.log(data);
  console.log(data2);
  console.log(data === data2);
  console.log(data.child === data2.child);
  console.log(data.show === data2.show);
  console.log(data.child[0] === data2.child[0]);
  console.log(data.child[0].child === data2.child[0].child);
  console.log(data.child[0].show === data2.child[0].show);
  console.log(data.child[0].child[0] === data2.child[0].child[0]);
  console.log(data.child[0].child[0].msg === data2.child[0].child[0].msg);
  console.log(data.child[0].child[0].show === data2.child[0].child[0].show);

  data2.child[0].child[0].name = "xiaoxiaozhang"

  data2.show();
  data2.child[0].show();
  data2.child[0].child[0].show();
  console.log( data.child[0].child[0].name );


  const o = {
    0:"hello",
    1:"world",
    2:{name:"hahah"},
    3:["a","b"],
    4:function(){},
    length: 5
  };

  const o2 = deepCopy(o);
  console.log(o)
  console.log(o2)
  console.log(o === o2)
  console.log(o[2] === o2[2])
  console.log(o[3] === o2[3])
  console.log(o[4] === o2[4])


  // for-in不仅可以遍历对象自身的属性，还会遍历到原型身上的属性
  // 借助：对象.hasOwnProperty( key )判断该属性是否属于对象自身


  // 不考虑元素的深拷贝
  // 不考虑基本数据的深拷贝


</script>
</html>